package cn.colins.raft.enity;

import cn.colins.raft.LogManage;
import cn.colins.raft.ResourceLifeCycle;
import cn.colins.raft.config.ServerConfig;
import cn.colins.raft.enums.NodeStatusEnums;
import cn.colins.raft.task.ElectionTask;
import cn.colins.raft.task.HeartBeatTask;
import cn.colins.raft.utils.ThreadPoolUtils;

import java.util.List;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

/**
 * @program: raft-java-demo
 * @description: 全局节点信息
 * @author: colins
 * @create: 2023-07-15 14:20
 **/
public class RaftNodeInfo {

    /**
     * 自己
     */
    private ServerConfig self;

    /**
     * 集群其他节点信息
     */
    private List<ServerConfig> clusterConfig;

    /**
     * 当前节点状态
     */
    private volatile NodeStatusEnums currentNodeStatus = NodeStatusEnums.FOLLOW;

    /**
     * 当前节点任期
     */
    private volatile long currentTerm = 0L;

    /**
     * 当前leader
     */
    private volatile String currentLeaderId;

    /**
     * 最后日志索引 已提交的
     */
    private volatile long lastLogIndex = 0L;

    /**
     * 最后的日志任期 这我这没用到
     */
    private volatile long lastLogTerm = 0L;

    /**
     * 当前任期给谁投过票
     */
    private volatile String voteFor;

    /**
     * 最近更新时间  心跳或者日志更新
     **/
    private volatile long lastUpdateTime = 0L;

    /**
     * 心跳任务
     **/
    private ScheduledFuture heartBeatTask;

    /**
     * 心跳检测任务
     **/
    private ScheduledFuture electionTask;

    /**
     * 日志管理
     **/
    private LogManage logManage;

    /**
     * 日志文件
     **/
    private String logPath;


    private static RaftNodeInfo INSTANCE = new RaftNodeInfo();

    private RaftNodeInfo() {

    }

    public static RaftNodeInfo getInstance() {
        return INSTANCE;
    }


    /**
     * 获取当前节点任期
     */
    public long getCurrentTerm() {
        return this.currentTerm;
    }

    public void setCurrentTerm(long maxCurrentTerm) {
        this.currentTerm = maxCurrentTerm;
    }

    /**
     * 发起投票请求的任期 = 当前任期 +1
     */
    public synchronized void setCallVoteTerm() {
        this.currentTerm++;
    }

    /**
     * 已提交的日志索引 +1
     */
    public synchronized void setCommitLastLogIndex() {
        this.lastLogIndex++;
    }


    public synchronized void setCurrentLeader(String currentLeaderId) {
        this.currentLeaderId = currentLeaderId;
    }

    public String getCurrentLeader() {
        return this.currentLeaderId;
    }

    public NodeStatusEnums getCurrentNodeStatus() {
        return currentNodeStatus;
    }

    public void setCurrentNodeStatus(NodeStatusEnums currentNodeStatus) {
        this.currentNodeStatus = currentNodeStatus;
    }

    public long getLastLogIndex() {
        return lastLogIndex;
    }

    public void setLastLogIndex(long lastLogIndex) {
        this.lastLogIndex = lastLogIndex;
    }

    public long getLastLogTerm() {
        return lastLogTerm;
    }

    public void setLastLogTerm(long lastLogTerm) {
        this.lastLogTerm = lastLogTerm;
    }

    public ServerConfig getSelf() {
        return self;
    }

    public void setSelf(ServerConfig self) {
        this.self = self;
    }

    public String getVoteFor() {
        return voteFor;
    }

    public void setVoteFor(String voteFor) {
        this.voteFor = voteFor;
    }

    public long getLastUpdateTime() {
        return lastUpdateTime;
    }

    public void setLastUpdateTime(long lastUpdateTime) {
        this.lastUpdateTime = lastUpdateTime;
    }

    public synchronized ScheduledFuture getHeartBeatTask() {
        return heartBeatTask;
    }

    public synchronized void setHeartBeatTask(ScheduledFuture heartBeatTask) {
        this.heartBeatTask = heartBeatTask;
    }

    public synchronized ScheduledFuture getElectionTask() {
        return electionTask;
    }

    public synchronized void setElectionTask(ScheduledFuture electionTask) {
        this.electionTask = electionTask;
    }


    public List<ServerConfig> getClusterConfig() {
        return clusterConfig;
    }

    public void setClusterConfig(List<ServerConfig> clusterConfig) {
        this.clusterConfig = clusterConfig;
    }


    public LogManage getLogManage() {
        return logManage;
    }

    public void setLogManage(LogManage logManage) {
        this.logManage = logManage;
    }

    public String getLogPath() {
        return logPath;
    }

    public void setLogPath(String logPath) {
        this.logPath = logPath;
    }
}
